package cn.dduan.fool.design.pattern.structure.flyweight;

import java.util.HashMap;

/**
 * 享元模式
 * <p>
 * 优点：
 * 1、节约系统的开销，保证一个常用的对象只有一个
 * 2、外部状态不会影响内部状态，可以在不同环境下进行共享哦
 * <p>
 * 缺点：
 * 1、享元模式使逻辑变得更加复杂，需要将享元对象分出内部状态和外部状态
 * 2、并且为了使对象可以共享，外部状态在很多情况下是必须有的，比如围棋的位置。当读取外部状态时明显会增加运行时间
 * <p>
 * 应用场景：
 * 1、一个系统有大量细粒度化的对象，占据大量的内存
 * 2、对象大部分属性可以外部化，并且能将外部的属性放入内部属性中来
 * 3、使用享元模式需要维护享元池，所以要用那种常用的经常调用的对象可以使用享元模式
 *
 * @author dduan
 * @version 1.0
 * @date 2023/4/7
 */
public class FlyweightPattern {
    public static void main(String[] args) {
        IgoChessman b1, b2, w1, w2;
        //获取对应的工厂对象
        IgoChessmanFactory igoChessmanFactory = IgoChessmanFactory.getInstance();
        IgoChessmanFactory igoChessmanFactory1 = IgoChessmanFactory.getInstance();
        //判断是不是同一个对象。就是看是不是共享了。
        System.out.println(igoChessmanFactory.getClass().getSimpleName());
        b1 = IgoChessmanFactory.getIgoChessman("黑");
        b2 = IgoChessmanFactory.getIgoChessman("黑");
        System.out.println(b1 == b2);
        w1 = IgoChessmanFactory.getIgoChessman("白");
        w2 = IgoChessmanFactory.getIgoChessman("白");
        System.out.println(w1 == w2);
        b1.display();
        w1.display();
        w2.display();
        b2.display();
    }
}

/**
 * 围棋享元抽象类
 *
 * @author dduan
 * @version 1.0
 * @date 2023/4/7
 */
abstract class IgoChessman {
    //共享抽象方法棋子的颜色
    public abstract String chessColor();

    public void display() {
        System.out.println("棋子:" + this.chessColor());
    }
}

/**
 * 白棋类，实现具体的方法
 *
 * @author dduan
 * @version 1.0
 * @date 2023/4/7
 */
class WhiteChessman extends IgoChessman {
    @Override
    public String chessColor() {
        return "白色";
    }
}

/**
 * 黑棋类，实现具体的方法
 *
 * @author dduan
 * @version 1.0
 * @date 2023/4/7
 */
class BlackChessman extends IgoChessman {
    @Override
    public String chessColor() {
        return "黑色";
    }
}

/**
 * 工厂类，使用的是单例模式创建，将享元对象唯一化
 *
 * @author dduan
 * @version 1.0
 * @date 2023/4/7
 */
class IgoChessmanFactory {
    /**
     * 首先私有化自己的类
     */
    private static IgoChessmanFactory INSTANCE = new IgoChessmanFactory();
    /**
     * 创建享元池
     */
    private static HashMap<String, IgoChessman> ht;

    /**
     * 私有化构造函数自己创建自己
     */
    private IgoChessmanFactory() {
        //创建对应的棋子放进去.
        ht = new HashMap<String, IgoChessman>();
        IgoChessman white, black;
        white = new WhiteChessman();
        ht.put("白", white);
        black = new BlackChessman();
        //放入HASHTABLE
        ht.put("黑", black);
        System.out.println(ht.toString());
    }

    /**
     * 提供一个全局访问的方法
     *
     * @param
     * @return cn.dduan.fool.design.pattern.structure.flyweight.IgoChessmanFactory
     * @author dduan
     * @version 1.0
     * @date 2023/4/7
     */
    public static IgoChessmanFactory getInstance() {
        return IgoChessmanFactory.INSTANCE;
    }

    /**
     * 工厂方法创建对象
     *
     * @param name
     * @return cn.dduan.fool.design.pattern.structure.flyweight.IgoChessman
     * @author dduan
     * @version 1.0
     * @date 2023/4/7
     */
    public static IgoChessman getIgoChessman(String name) {
        return (IgoChessman) ht.get(name);

    }
}